package cn.jaye.fabric.domain.service;

import cn.jaye.fabric.common.constants.FabricConfig;
import cn.jaye.fabric.common.constants.FarbicConstant;
import cn.jaye.fabric.common.constants.Global;
import cn.jaye.fabric.common.constants.mapping.Config;
import org.hyperledger.fabric.sdk.Channel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.File;
import java.nio.file.Paths;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

/**
 * @author Jaye
 * @create 2018-05-09 16:18
 */
@Service
public class ConfigService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private FarbicConstant farbicConstant;

    public Properties createCaProperties(boolean enableTLS, String domainName) {
        Properties properties = new Properties();
        if (enableTLS) {
            String cert = farbicConstant.getPeerCaPemDefaultPath().replaceAll("DNAME", domainName);
            File cf = new File(cert);
            properties.setProperty("pemFile", cf.getAbsolutePath());
            properties.setProperty("allowAllHostNames", "true"); //testing environment only NOT FOR PRODUCTION!
        }
        return properties;
    }

    public Properties getProposalProperties() {
        Properties proposalProperties = new Properties();
        proposalProperties.put("ProposalWaitTime", 12000);
        proposalProperties.put("InvokeWaitTime", 20);
        return proposalProperties;
    }

    public Properties getOrdererProperties(String orderName, String domainName) {
        Properties ordererProperties = getEndPointProperties("orderer", orderName, domainName, "org1");
        ordererProperties.put(Global.WAIT_TIME_MILLISECS, "org.hyperledger.fabric.sdktest.ordererWaitTimeMilliSecs");
        ordererProperties.put(Global.GRPC_NETTY_CHANNEL_BUILDER_OPTION_KEEPALIVE_TIME, new Object[]{5L, TimeUnit.MINUTES});
        ordererProperties.put(Global.GRPC_NETTY_CHANNEL_BUILDER_OPTION_KEEPALIVE_TIMEOUT, new Object[]{8L, TimeUnit.SECONDS});
        System.setProperty("org.hyperledger.fabric.sdktest.ordererWaitTimeMilliSecs", "80000");
        return ordererProperties;
    }

    public Properties getPeerProperties(String name, String domainName, String orgName) {
        Properties peerProperties = getEndPointProperties("peer", name, domainName, orgName);
        peerProperties.put(Global.GRPC_NETTY_CHANNEL_BUILDER_OPTION_MAXINBOUND_MESSAGE_SIZE, 9000000);
        return peerProperties;
    }

    public Properties getEventHubProperties(String name, String domainName, String orgName) {
        Properties eventHubProperties = getEndPointProperties("peer", name, domainName, orgName);
        eventHubProperties.put(Global.GRPC_NETTY_CHANNEL_BUILDER_OPTION_KEEPALIVE_TIME, new Object[]{5L, TimeUnit.MINUTES});
        eventHubProperties.put(Global.GRPC_NETTY_CHANNEL_BUILDER_OPTION_KEEPALIVE_TIMEOUT, new Object[]{8L, TimeUnit.SECONDS});
        return eventHubProperties;
    }

    private Properties getEndPointProperties(final String type, final String name, final String domainName, String orgName) {

//        final String domainName = getDomainName(name);
        File cert;
        if ("orderer".equals(type)) {
            cert = Paths.get(farbicConstant.getKeyStoreLocation(), "crypto-config/ordererOrganizations".replace("orderer", type), domainName, type + "s",
                    name + "." + domainName, "tls/server.crt").toFile();
        } else {
            cert = Paths.get(farbicConstant.getKeyStoreLocation(), "crypto-config/ordererOrganizations".replace("orderer", type), orgName + "." + domainName, type + "s",
                    name, "tls/server.crt").toFile();
        }

        if (!cert.exists()) {
            throw new RuntimeException(String.format("Missing cert file for: %s. Could not find at location: %s", name,
                    cert.getAbsolutePath()));
        }

        Properties ret = new Properties();
        ret.setProperty("pemFile", cert.getAbsolutePath());
        //      ret.setProperty("trustServerCertificate", "true"); //testing environment only NOT FOR PRODUCTION!
        ret.setProperty("hostnameOverride", name);
        ret.setProperty("sslProvider", "openSSL");
        ret.setProperty("negotiationType", "TLS");

        return ret;
    }

    private String getDomainName(final String name) {
        int dot = name.indexOf(".");
        if (-1 == dot) {
            return null;
        } else {
            return name.substring(dot + 1);
        }
    }

    public void setChannel(Channel channel) {
        channel.setTransactionWaitTime(farbicConstant.getChannelTransactionWaitTime());
        channel.setDeployWaitTime(farbicConstant.getChannelDeployWaitTime());
    }
}
